package com.weijian.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.weijian.dal.dto.study.ProgressUpdateRequest;
import com.weijian.dal.dto.study.StudyRecordDTO;
import com.weijian.dal.dto.study.StudyStatisticsDTO;
import com.weijian.dal.entity.StudyRecord;
import com.weijian.dal.enums.StudyStatus;
import com.weijian.dal.mapper.StudyRecordMapper;
import com.weijian.service.StudyRecordService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.Duration;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 学习记录服务实现
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class StudyRecordServiceImpl implements StudyRecordService {

    private final StudyRecordMapper studyRecordMapper;
    private final RedisTemplate<String, Object> redisTemplate;

    private static final String STUDY_RECORD_CACHE_PREFIX = "study:record:";
    private static final String STUDY_LEADERBOARD_PREFIX = "study:leaderboard:";

    @Override
    @Transactional
    public StudyRecordDTO startStudy(Long userId, Long courseId) {
        log.info("用户 {} 开始学习课程 {}", userId, courseId);

        // 检查是否已存在学习记录
        StudyRecord existingRecord = studyRecordMapper.selectByUserAndCourse(userId, courseId);
        if (existingRecord != null) {
            return convertToDTO(existingRecord);
        }

        // 创建新的学习记录
        StudyRecord record = new StudyRecord();
        record.setUserId(userId);
        record.setCourseId(courseId);
        record.setStatus(StudyStatus.IN_PROGRESS);
        record.setProgressPercent(0);
        record.setCompletedChapters(0);
        record.setStudyDuration(0L);
        record.setFirstStudyTime(LocalDateTime.now());
        record.setLastStudyTime(LocalDateTime.now());

        // 获取课程章节数（从课程表获取）
        // TODO: 需要从课程服务获取实际章节数
        record.setTotalChapters(10);

        studyRecordMapper.insert(record);

        // 缓存学习记录
        cacheStudyRecord(record);

        return convertToDTO(record);
    }

    @Override
    @Transactional
    public StudyRecordDTO updateProgress(Long userId, ProgressUpdateRequest request) {
        log.info("用户 {} 更新课程 {} 学习进度", userId, request.getCourseId());

        StudyRecord record = studyRecordMapper.selectByUserAndCourse(userId, request.getCourseId());
        if (record == null) {
            throw new RuntimeException("学习记录不存在");
        }

        // 更新进度（将逻辑从实体类移到服务类）
        updateStudyRecordProgress(record, request.getCompletedChapters(),
                request.getStudyDuration() != null ? request.getStudyDuration() : 0L);

        studyRecordMapper.updateById(record);

        // 更新缓存
        cacheStudyRecord(record);

        // 更新排行榜
        if (request.getStudyDuration() != null && request.getStudyDuration() > 0) {
            updateLeaderboard(userId, record.getStudyDuration());
        }

        return convertToDTO(record);
    }

    /**
     * 更新学习记录进度
     * @param record 学习记录
     * @param completedChapters 已完成章节数
     * @param additionalDuration 额外学习时长
     */
    private void updateStudyRecordProgress(StudyRecord record, int completedChapters, long additionalDuration) {
        record.setCompletedChapters(completedChapters);
        record.setStudyDuration(record.getStudyDuration() + additionalDuration);

        if (record.getTotalChapters() != null && record.getTotalChapters() > 0) {
            int progressPercent = (int) Math.round((double) completedChapters / record.getTotalChapters() * 100);
            record.setProgressPercent(progressPercent);
        }

        record.setLastStudyTime(LocalDateTime.now());

        // 检查是否完成
        if (record.getTotalChapters() != null && completedChapters >= record.getTotalChapters()) {
            record.setStatus(StudyStatus.COMPLETED);
            record.setProgressPercent(100);
            record.setCompletionTime(LocalDateTime.now());
        }
    }


    @Override
    @Transactional
    public StudyRecordDTO completeCourse(Long userId, Long courseId) {
        log.info("用户 {} 完成课程 {} 学习", userId, courseId);

        StudyRecord record = studyRecordMapper.selectByUserAndCourse(userId, courseId);
        if (record == null) {
            throw new RuntimeException("学习记录不存在");
        }

        // 标记为完成
        record.setStatus(StudyStatus.COMPLETED);
        record.setProgressPercent(100);
        record.setCompletedChapters(record.getTotalChapters());
        record.setCompletionTime(LocalDateTime.now());

        studyRecordMapper.updateById(record);

        // 更新缓存
        cacheStudyRecord(record);

        return convertToDTO(record);
    }

    @Override
    public StudyRecordDTO getStudyRecord(Long userId, Long courseId) {
        String cacheKey = STUDY_RECORD_CACHE_PREFIX + userId + ":" + courseId;

        // 先查缓存
        StudyRecord record = (StudyRecord) redisTemplate.opsForValue().get(cacheKey);
        if (record != null) {
            return convertToDTO(record);
        }

        // 查数据库
        record = studyRecordMapper.selectByUserAndCourse(userId, courseId);
        if (record != null) {
            cacheStudyRecord(record);
            return convertToDTO(record);
        }

        return null;
    }

    @Override
    public IPage<StudyRecordDTO> getUserStudyRecords(Page<StudyRecordDTO> page, Long userId) {
        return studyRecordMapper.selectUserStudyRecords(page, userId);
    }

    @Override
    public List<StudyRecordDTO> getInProgressCourses(Long userId) {
        return studyRecordMapper.selectInProgressCourses(userId);
    }

    @Override
    public List<StudyRecordDTO> getCompletedCourses(Long userId) {
        return studyRecordMapper.selectCompletedCourses(userId);
    }

    /**
     * 统计用户的学习情况
     */
    @Override
    public StudyStatisticsDTO getUserStudySummary(Long userId) {
        String cacheKey = "study:summary:" + userId;

        // 先尝试从缓存获取
        StudyStatisticsDTO summary = (StudyStatisticsDTO) redisTemplate.opsForValue().get(cacheKey);
        if (summary != null) {
            return summary;
        }

        // 从数据库查询
        summary = studyRecordMapper.selectUserStudySummary(userId);

        // 如果查询结果为空，创建默认统计对象
        if (summary == null) {
            summary = new StudyStatisticsDTO();
            summary.setTotalCourses(0);
            summary.setCompletedCourses(0);
            summary.setTotalStudyDuration(0L);
            summary.setLastStudyTime(null);
        }

        // 缓存结果，有效期30分钟
        redisTemplate.opsForValue().set(cacheKey, summary, Duration.ofMinutes(30));

        return summary;
    }

    @Override
    public List<StudyRecordDTO> getStudyLeaderboard(String type) {
        String key = STUDY_LEADERBOARD_PREFIX + type;

        // 从Redis获取排行榜
        Set<ZSetOperations.TypedTuple<Object>> leaderboard =
                redisTemplate.opsForZSet().reverseRangeWithScores(key, 0, 9);

        if (leaderboard == null || leaderboard.isEmpty()) {
            return List.of();
        }

        return leaderboard.stream()
                .map(tuple -> {
                    StudyRecordDTO dto = new StudyRecordDTO();
                    dto.setUserId(Long.valueOf(tuple.getValue().toString()));
                    dto.setStudyDuration(tuple.getScore().longValue());
                    return dto;
                })
                .collect(Collectors.toList());
    }

    /**
     * 缓存学习记录
     */
    private void cacheStudyRecord(StudyRecord record) {
        String cacheKey = STUDY_RECORD_CACHE_PREFIX + record.getUserId() + ":" + record.getCourseId();
        redisTemplate.opsForValue().set(cacheKey, record, 24, TimeUnit.HOURS);
    }

    /**
     * 更新排行榜
     */
    private void updateLeaderboard(Long userId, Long totalStudyDuration) {
        String dailyKey = STUDY_LEADERBOARD_PREFIX + "daily";
        String weeklyKey = STUDY_LEADERBOARD_PREFIX + "weekly";
        String overallKey = STUDY_LEADERBOARD_PREFIX + "overall";

        // 更新总学习时长
        redisTemplate.opsForZSet().incrementScore(overallKey, userId.toString(), totalStudyDuration);
        redisTemplate.expire(dailyKey, 1, TimeUnit.DAYS);
        redisTemplate.expire(weeklyKey, 7, TimeUnit.DAYS);
    }

    /**
     * 转换为DTO
     */
    private StudyRecordDTO convertToDTO(StudyRecord record) {
        StudyRecordDTO dto = new StudyRecordDTO();
        dto.setId(record.getId());
        dto.setUserId(record.getUserId());
        dto.setCourseId(record.getCourseId());
        dto.setStatus(record.getStatus());
        dto.setProgressPercent(record.getProgressPercent());
        dto.setTotalChapters(record.getTotalChapters());
        dto.setCompletedChapters(record.getCompletedChapters());
        dto.setFirstStudyTime(record.getFirstStudyTime());
        dto.setLastStudyTime(record.getLastStudyTime());
        dto.setCompletionTime(record.getCompletionTime());
        dto.setStudyDuration(record.getStudyDuration());
        return dto;
    }
}